package com.tongfusoft.web.core.service.impl;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ibatis.jdbc.SqlBuilder;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;

import com.tongfusoft.da.help.DBUtils;
import com.tongfusoft.exception.ServiceException;
import com.tongfusoft.web.core.Constant;
import com.tongfusoft.web.core.action.ExportDefine;
import com.tongfusoft.web.core.data.Page;
import com.tongfusoft.web.core.data.User;
import com.tongfusoft.web.core.service.IListService;
import com.tongfusoft.web.core.service.impl.list.ClasspathListResourceBundle;
import com.tongfusoft.web.core.service.impl.list.ListResourceBundle;
import com.tongfusoft.web.core.service.impl.list.ListResourceElement;

public class ListServiceAdapter implements IListService{
	protected Log logger = LogFactory.getLog(ListServiceAdapter.class);
	
	/**
	 * 所有的list配置信息
	 */
	public static ListResourceBundle LISTRB = new ClasspathListResourceBundle();
	
	static{
		LISTRB.getListResources();
		LISTRB.parserElement();
	}
	
	
	/**
	 * eg : 等于
	 * ne ：不等于
	 * lt ：小于
	 * le ：小于等于
	 * gt ：大于
	 * ge ：大于等于
	 * nu ：is null
	 * nn : is not null
	 * in : 属于
	 * ni ：不属于
	 * bw : 开始于
	 * bn : 不开始于
	 * ew : 结束于
	 * en ：不结束于
	 * cn : 包含
	 * nc : 不包含
	 * 
	 * @author shadowguo
	 *
	 */
	public static Map<String,String> OPERATORS = new HashMap<String,String>();
	static{
		OPERATORS.put("eq", "=");
		OPERATORS.put("ne", "<>");
		OPERATORS.put("lt", "<");
		OPERATORS.put("le", "<=");
		OPERATORS.put("gt", ">");
		OPERATORS.put("ge", ">=");
		OPERATORS.put("nu", "is null");
		OPERATORS.put("nn", "is not null");
		OPERATORS.put("in", "in");
		OPERATORS.put("ni", "not in");
		OPERATORS.put("bw", "");
		OPERATORS.put("bn", "");
		OPERATORS.put("ew", "");
		OPERATORS.put("en", "");
		OPERATORS.put("cn", "like");
		OPERATORS.put("nc", "not like");
	}
	
	
	protected Map<String,Object> fillParams(Map map,Map params){
		//设定一些常用的值
		params.put("userName", ((User)map.get(Constant.SESSION_USER)).getUserDisplayName());
		params.put("userId", ((User)map.get(Constant.SESSION_USER)).getPkValue());
		
		//如果查找中有包含操作符，需要增加%
		if(map.get(IListService.SEARCHOPER)!= null && map.get(IListService.SEARCHSTRING) != null 
				&& ("nc".equals((String)map.get(IListService.SEARCHOPER)) || "cn".equals((String)map.get(IListService.SEARCHOPER)))){
			map.put(IListService.SEARCHSTRING,"%" + map.get(IListService.SEARCHSTRING) + "%");
		}
		
		//遍历所有的值，加入到params
		params.putAll(map);
		
		return params;
	}
	
	
	protected Map<String,Object> buildSqlFragmentAndParams(Map map){
		Map<String,Object> result = new HashMap<String,Object>();
		//加入默认的值
		result.putAll(map);
		
		StringBuffer sb = new StringBuffer();
		if (map.containsKey(IListService.SEARCHFIELD)
				&& StringUtils.isNotEmpty((String) map.get(IListService.SEARCHFIELD))
				&& map.containsKey(IListService.SEARCHOPER)
				&& StringUtils.isNotEmpty((String) map.get(IListService.SEARCHOPER))
				&& map.containsKey(IListService.SEARCHSTRING)
				&& StringUtils.isNotEmpty((String) map.get(IListService.SEARCHSTRING))) {
			//简单查询条件
			sb.append(map.get(IListService.SEARCHFIELD)).append(" ").append(OPERATORS.get(map.get(IListService.SEARCHOPER))).append(" #{").append(SEARCHSTRING).append("}");
			
			result.put(IListService.SQLFRAGMENT, sb.toString());
			result.put(IListService.SEARCHSTRING, warpParam((String)map.get(IListService.SEARCHOPER),map.get(IListService.SEARCHSTRING)));
		}else{
		
		//复合查询
/*		{"groupOp":"OR",
			"rules":[
			         {"field":"b.pro_code","op":"eq","data":"ddd"},
			         {"field":"b.pro_name","op":"cn","data":"uuuu"},
			         {"field":"a.display_name","op":"eq","data":"sss"}
		]}*/
			if(map.containsKey(IListService.FILTERS) && StringUtils.isNotEmpty((String) map.get(IListService.FILTERS))){
				JSONObject json = JSONObject.fromObject(map.get(IListService.FILTERS));
				JSONArray rules = json.getJSONArray("rules");
				for(int i=0;i<rules.size();i++){
					JSONObject rule = rules.getJSONObject(i);
					//拼接SQL
					sb.append(rule.getString("field")).append(" ").append(OPERATORS.get(rule.getString("op"))).append(" #{field").append(i).append("} ");
					if(i + 1 < rules.size()){
						sb.append(json.getString("groupOp")).append(" ");
					}
					
					//组装参数
					result.put("field"+i, warpParam(rule.getString("op"),rule.get("data")));
				}
				
				result.put(IListService.SQLFRAGMENT, sb.toString());
			}
		}
		
		return result;
	}
	
	
	/**
	 * 包装值对象
	 * @param op
	 * @param value
	 * @return
	 */
	protected Object warpParam(String op,Object value){
		if(op.equals("cn") || op.equals("nc")){
			value = "%"+value+"%";
		}
		
		return value;
	}
	
	/**
	 * 获取导出Excel的标题
	 */
	public List<ExportDefine> getExportTitle(Map map){
		String key = (String)map.get(Constant.GRID_KEY);
		if(logger.isDebugEnabled()){
			logger.debug("list gridKey:" + key);
		}
		
		if(StringUtils.isNotEmpty(key)){
			ListResourceElement element = LISTRB.getListElement(key);
			return element.getTitleDef();
		}
		
		return null;
	}
	
	/**
	 * 拼接SQL
	 * @param map
	 * @return
	 */
	protected String genSQL(Map map,Page page){
		String key = (String)map.get(Constant.GRID_KEY);
		
		if(logger.isDebugEnabled()){
			logger.debug("list gridKey:" + key);
		}
		
		if(StringUtils.isNotEmpty(key)){
			ListResourceElement element = LISTRB.getListElement(key);
			SqlBuilder.SELECT(element.getSelect());
			SqlBuilder.FROM(element.getFrom());
			if(StringUtils.isNotEmpty(element.getWhere())){
				SqlBuilder.WHERE(element.getWhere());
			}
			
			Map params = buildSqlFragmentAndParams(map);
			if (params.containsKey(IListService.SQLFRAGMENT)) {
				SqlBuilder.WHERE((String) params.get(IListService.SQLFRAGMENT));
			}

			if (page != null && StringUtils.isNotEmpty(page.getOrderBy())) {
				if (StringUtils.isNotEmpty(page.getOrder())) {
					SqlBuilder.ORDER_BY(page.getOrderBy() + " " + page.getOrder());
				} else {
					SqlBuilder.ORDER_BY(page.getOrderBy() + " desc ");
				}
			} else{
				if(StringUtils.isNotEmpty(element.getOrderby())){
					SqlBuilder.ORDER_BY(element.getOrderby());
				}
			}
			
			return SqlBuilder.SQL();
		}else{
			throw new ServiceException("not find gridKey");
		}
	}
	
	
	@Override
	public int getTotalCount(Map map) {
		StringBuffer sql = new StringBuffer();
		sql.append("select count(*) as totalnum from ( ");
		sql.append(genSQL(map,null));
		sql.append(" )  ") ;
		
		if(logger.isDebugEnabled()){
			logger.debug("select count sql :" + sql.toString());
		} 

		Map params = buildSqlFragmentAndParams(map);
		
		if(logger.isDebugEnabled()){
			try {
				logger.debug("request params:" + Constant.OBJECTMAPPER.writeValueAsString(params));
			} catch (Exception e) {
				logger.debug("request params:" + params);
			}
		} 
		
		List<Map<String, Object>> result = DBUtils.executeSelectDynamic(sql.toString(),params);
		return ((Number) result.get(0).get("TOTALNUM")).intValue();
	}
	
	@Override
	public Page findOnPage(Map map, Page page) {
		Map params = buildSqlFragmentAndParams(map);
		String sql = genSQL(map,page);
		
		if(logger.isDebugEnabled()){
			logger.debug("select data sql :" + sql);
			logger.debug("Page Content:" + page.toString());
		} 
		
		page.setResult(DBUtils.executeSelectDynamic(sql, page.getPageSize(),
				page.getPageSize() * (page.getPageNo() - 1), params));
		return page;
	}
}
